////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the Microsoft Public License (Ms-PL).
// See accompanying file License.txt or copy at http://mews.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Mews
{
    /// <summary>Exposes the methods implemented by all visitors.</summary>
    /// <typeparam name="TVisitableBase">The visitable base type.</typeparam>
    /// <remarks>This interface is a part of an implementation of the
    /// <a href="http://www.objectmentor.com/resources/articles/acv.pdf">acyclic visitor pattern</a>.</remarks>
    /// <threadsafety static="true" instance="false"/>
    public interface IVisitor<TVisitableBase> where TVisitableBase : IVisitable<TVisitableBase>
    {
        /// <summary>Is called when a concrete visitor does not implement <see cref="IVisitor{T, U}"/>, passing the
        /// derived type of <paramref name="visitable"/> as TVisitableDerived.</summary>
        /// <param name="visitable">The object being visited.</param>
        /// <remarks>Since a call to this method usually means that a new visitable type has been added but the visitor
        /// has not been adapted accordingly, implementations of this method will normally want to throw an exception.
        /// </remarks>
        void OnVisit(TVisitableBase visitable);
    }

    /// <summary>Exposes the methods implemented by visitors that are capable of visiting objects of type
    /// <typeparamref name="TVisitableDerived"/>.</summary>
    /// <typeparam name="TVisitableDerived">The type that a visitor implementing this interface is capable of visiting.
    /// </typeparam>
    /// <typeparam name="TVisitableBase">The visitable base type.</typeparam>
    /// <remarks>
    /// <para>Clients usually subtype this interface with their own generic interface, which only takes a
    /// <typeparamref name="TVisitableDerived"/> parameter. A concrete visitor then implements that interface once for
    /// each type that the visitor wants to visit.</para>
    /// <para>This interface is a part of an implementation of the 
    /// <a href="http://www.objectmentor.com/resources/articles/acv.pdf">acyclic visitor pattern</a>.</para>
    /// </remarks>
    /// <threadsafety static="true" instance="false"/>
    public interface IVisitor<TVisitableDerived, TVisitableBase> : IVisitor<TVisitableBase>
        where TVisitableDerived : IVisitable<TVisitableDerived, TVisitableBase>
        where TVisitableBase : IVisitable<TVisitableBase>
    {
        /// <summary>Is called when the type being visited is of type <typeparamref name="TVisitable"/>.</summary>
        /// <param name="visitable">The object being visited.</param>
        void OnVisit(TVisitableDerived visitable);
    }
}
